home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1996 #15
/
Monster Media Number 15 (Monster Media)(July 1996).ISO
/
cad
/
lasi512b.zip
/
TILT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-04
|
23KB
|
1,025 lines
//This is the source code for the TILT.EXE utility program. It is included
//as an example of how to write simple programs that work with LASI cells
//in TLC format. Most of the functions are generic and may be used in other
//programs. Compile with Microsoft C/C++ (or other compiler) in small model.
//*****************
// TLC Tilter v5.1
// by d.e.boyce
//*****************
#include <stdio.h>
#include <math.h>
#include <graph.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define PSS 512
#define IL 32767
#define LIL 8388607
#define PIX2 6.2831853
#define PIF 3.1415926
#define PID2 1.5707963
#define DR 57.29577951
#define TLCLIM 100
//function prototypes
int ropenTLC(char *);
int wopenTLC(char *);
int read4eqCode(void);
int read4Hdr(void);
int readC(void);
int readB(void);
int readP(void);
int readT(void);
void writeH(void);
void writeC(void);
void writeB(void);
void writeP(void);
void writeT(void);
void makeH(void);
void makeC(void);
void makeP(void);
void makeB(void);
void makeT(void);
void path2poly(void);
int pathSeg(long,int,int,int);
int makeTLCxy(void);
int abrtCk(void);
long lround(double);
void Tilt(void);
void tiltX(double,double);
void tiltY(double,double);
void tiltZ(double,double);
char *chop(char *,int);
char *tiltname(char *);
int dsign(double);
void HELP(void);
//global variables
char header[]="\nLASI TLC Tilter Version 5.1\n\n";
//command line variables
double ang1,ang2,ang3,lspace,cspace;
double cos1,cos2,cos3,sin1,sin2,sin3;
char axis1,axis2,axis3;
//coordinate variables
long nx,ny,nz,p1,p2,p3,q1,q2,q3;
int npp;
//poly coord array
long px[PSS],py[PSS];
//TLC file structs
FILE *rTLCfile,*wTLCfile;
//TLC record structs
struct tlchdr
{
char name[10];
char lv[6];
char tv[6];
double scale;
char punit[6];
char date[9];
char time[9];
int rnk;
long l;
long b;
long r;
long t;
int bn;
int pn;
unsigned vn;
int cn;
} TLCh={"","5.1","5.1",20,"um",1,0,0,10,10,0,0,0,0};
struct tlccel
{
char name[9];
int o;
long x;
long y;
int r;
} TLCc;
struct tlcbox
{
int lyr;
long l;
long b;
long r;
long t;
} TLCb;
struct tlcpath
{
int lyr;
long w;
int nv;
long x[PSS];
long y[PSS];
} TLCp;
struct tlctext
{
int lyr;
long siz;
int nv;
int o;
long x;
long y;
char txt[41];
} TLCt;
//*************
//start of main
//*************
main(int argc,char *argv[])
{
int cp=0;
_clearscreen(_GCLEARSCREEN);
printf("%s",header);
if(argc<6){
HELP();
return 0;
}
//command line param
ang1=atof(argv[1]);
axis1=tolower(argv[1][strlen(argv[1])-1]);
ang2=atof(argv[2]);
axis2=tolower(argv[2][strlen(argv[2])-1]);
ang3=atof(argv[3]);
axis3=tolower(argv[3][strlen(argv[3])-1]);
lspace=atof(argv[4]);
cspace=atof(argv[5]);
//angle cos and sin
cos1=cos(ang1/DR);
sin1=sin(ang1/DR);
cos2=cos(ang2/DR);
sin2=sin(ang2/DR);
cos3=cos(ang3/DR);
sin3=sin(ang3/DR);
printf("Tilting %gdeg in %c %gdeg in %c %gdeg in %c\n\n",
ang1,axis1,ang2,axis2,ang3,axis3);
//TLC file tilter loop
for(cp=6;cp<argc;cp++){
if(!ropenTLC(argv[cp]))
continue;
if(!wopenTLC(argv[cp]))
continue;
read4Hdr();
//init counts to 0
TLCh.bn=TLCh.pn=TLCh.vn=TLCh.cn=0;
rewind(rTLCfile);
read4eqCode();
makeH();
printf(" %s.TLC File Generated!\n",tiltname(argv[cp]));
_fcloseall();
if(abrtCk()) break;
}
return 0;
}
//******************
//start of functions
//******************
//read TLC header info
int read4Hdr(void)
{
static char buf[TLCLIM];
char *s;
buf[0]=0;
while(!feof(rTLCfile)){
if(!strncmp(fgets(buf,TLCLIM,rTLCfile),"=H",2)){
fgets(buf,TLCLIM,rTLCfile);
strcpy(TLCh.name,chop(buf,8));
fgets(buf,TLCLIM,rTLCfile);
strcpy(TLCh.lv,chop(buf,5));
fgets(buf,TLCLIM,rTLCfile);
strcpy(TLCh.tv,chop(buf,5));
fgets(buf,TLCLIM,rTLCfile);
TLCh.scale=atof(buf);
fgets(buf,TLCLIM,rTLCfile);
strcpy(TLCh.punit,chop(buf,6));
fgets(buf,TLCLIM,rTLCfile);
strcpy(TLCh.date,chop(buf,13));
fgets(buf,TLCLIM,rTLCfile);
strcpy(TLCh.time,chop(buf,10));
fgets(buf,TLCLIM,rTLCfile); //outline
chop(buf,36);
if((s=strtok(buf," "))==NULL) return 0;
TLCh.rnk=atoi(s);
if((s=strtok(NULL," "))==NULL) return 0;
TLCh.l=atol(s);
if((s=strtok(NULL," "))==NULL) return 0;
TLCh.b=atol(s);
if((s=strtok(NULL," "))==NULL) return 0;
TLCh.r=atol(s);
if((s=strtok(NULL," "))==NULL) return 0;
TLCh.t=atol(s);
fgets(buf,TLCLIM,rTLCfile); //count
chop(buf,30);
if((s=strtok(buf," "))==NULL) return 0;
TLCh.bn=atoi(s);
if((s=strtok(NULL," "))==NULL) return 0;
TLCh.pn=atoi(s);
if((s=strtok(NULL," "))==NULL) return 0;
TLCh.vn=atoi(s);
if((s=strtok(NULL," "))==NULL) return 0;
TLCh.cn=atoi(s);
}
}
return 1;
}
//read for record types then write new records
int read4eqCode(void)
{
static char buf[TLCLIM];
buf[0]=0;
while(!feof(rTLCfile)){
fgets(buf,TLCLIM,rTLCfile);
if(feof(rTLCfile)) //eof check
break;
if(!strncmp(buf,"=C",2)){
if(readC())
makeC();
else
printf(" Cell Record Read Error!\n");
continue;
}
if(!strncmp(buf,"=B",2)){
if(readB())
makeB();
else
printf(" Box Record Read Error!\n");
continue;
}
if(!strncmp(buf,"=P",2)){
if(readP())
makeP();
else
printf(" Path Record Read Error!\n");
continue;
}
if(!strncmp(buf,"=T",2)){
if(readT())
makeT();
else
printf(" Text Record Read Error!\n");
continue;
}
}
return 1;
}
void makeH(void)
{
char *p;
p=tiltname(TLCh.name);
strcpy(TLCh.name,p);
nx=TLCh.l;ny=TLCh.b;nz=0;
Tilt();
TLCh.l=nx;TLCh.b=ny;
nx=TLCh.r;ny=TLCh.t;nz=0;
Tilt();
TLCh.r=nx;TLCh.t=ny;
writeH();
}
void makeC(void)
{
char *p;
//change name and tilt ref point
p=tiltname(TLCc.name);
nz=(long)((TLCh.rnk-1)*cspace*TLCh.scale);
strcpy(TLCc.name,p);
nx=TLCc.x;ny=TLCc.y;
Tilt();
TLCc.x=nx;TLCc.y=ny;
writeC();
}
void makeB(void)
{
long z;
//change box to polygon
TLCp.lyr=TLCb.lyr;
TLCp.w=0;
TLCp.nv=5;
z=(long)((TLCb.lyr-1)*lspace*TLCh.scale);
nx=TLCb.l;ny=TLCb.b;nz=z;
Tilt();
TLCp.x[0]=nx;TLCp.y[0]=ny;
nx=TLCb.r;ny=TLCb.b;nz=z;
Tilt();
TLCp.x[1]=nx;TLCp.y[1]=ny;
nx=TLCb.r;ny=TLCb.t;nz=z;
Tilt();
TLCp.x[2]=nx;TLCp.y[2]=ny;
nx=TLCb.l;ny=TLCb.t;nz=z;
Tilt();
TLCp.x[3]=nx;TLCp.y[3]=ny;
TLCp.x[4]=TLCp.x[0];
TLCp.y[4]=TLCp.y[0];
writeP();
}
void makeT(void)
{
//tilt text ref point
nz=(long)((TLCt.lyr-1)*lspace*TLCh.scale);
nx=TLCt.x;ny=TLCt.y;
Tilt();
TLCt.x=nx;TLCt.y=ny;
writeT();
}
void makeP(void)
{
int p=0;
long z;
z=(long)((TLCp.lyr-1)*lspace*TLCh.scale);
if(TLCp.w!=0){
path2poly();
TLCp.w=0;
}
while(p<TLCp.nv){
nx=TLCp.x[p];ny=TLCp.y[p];nz=z;
Tilt();
TLCp.x[p]=nx;TLCp.y[p]=ny;
p++;
}
writeP();
}
//TLC poly from TLC path
void path2poly(void)
{
int p,nv=0,first,ext;
long hw;
//no poly allowed
if(TLCp.w==0) return;
// extended end
if(TLCp.w>0) ext=0; else ext=1;
// init expansion
npp=0; //expand point number
first=1; //first vertex
hw=labs(TLCp.w)/2; //half path width
p=0;
p1=TLCp.x[p]; //do first point
q1=TLCp.y[p++];
//path expansion loop
while(p<TLCp.nv){
p2=TLCp.x[p];
q2=TLCp.y[p];
if(p1==p2 && q1==q2) //point1==point2
goto skip;
if(p+1<TLCp.nv){ //look ahead
p3=TLCp.x[p+1];
q3=TLCp.y[p+1];
if(p2==p3 && q2==q3) //point2==point3
goto skip;
}
pathSeg(hw,first,p+1,ext); //make segs
first=0;
skip: //skip to next coord
p1=p2;
q1=q2;
p++;
}
TLCp.nv=makeTLCxy()+1;
}
//make a path segment
int pathSeg(long w2,int first,int nv,int ext)
{
static int k,aa;
double s,c;
long x1,x2,x3,x4;
long y1,y2,y3,y4;
double fx,fy,fcc,fss,f,fn,fh,fhc,fhs;
double fa,fta;
// corners:
// ---2-----------------4---
// | |
// p1,q1 p2,q2
// | |
// ---1-----------------3---
// make side lines
// get trig
fx=p2-p1;
fy=q2-q1;
fa=atan2(fy,fx);
fcc=cos(fa);
fss=sin(fa);
s=w2*fss;
c=w2*fcc;
// first coordinate pair
if(first){
// segment beginning
aa=0;
x1=lround(p1+s);
y1=lround(q1-c);
x2=lround(p1-s);
y2=lround(q1+c);
// extended end
if(ext){
x1=lround(x1-c);
y1=lround(y1-s);
x2=lround(x2-c);
y2=lround(y2-s);
}
// save first points
px[npp]=x1;
py[npp]=y1;
npp++;
px[npp]=x2;
py[npp]=y2;
}
else{
if(aa){ // acute corner
x1=lround(p1+s-k*c);
y1=lround(q1-c-k*s);
x2=lround(p1-s+k*c);
y2=lround(q1+c+k*s);
npp++;
px[npp]=x1; //extra vertex
py[npp]=y1;
npp++;
px[npp]=x2;
py[npp]=y2;
aa=0;
}
else{
//next coords from last coords
x1=x3;
x2=x4;
y1=y3;
y2=y4;
}
}
// second coordinate pair
//next corner coordinates
if(nv>=TLCp.nv){
// segment end
x3=lround(p2+s);
y3=lround(q2-c);
x4=lround(p2-s);
y4=lround(q2+c);
if(ext){
// extended end
x3=lround(x3+c);
y3=lround(y3+s);
x4=lround(x4+c);
y4=lround(y4+s);
}
}
else{
// look at next segment
fta=fa;
fx=p3-p2;
fy=q3-q2;
fa=atan2(fy,fx);
f=(fa-fta)/2;
fn=cos(f);
if(fn){ // not 180 deg bend
fh=w2*sin(f)/fn;
k=dsign(fh);
}
else{ // 180 deg bend
fh=2*w2;
k=0;
}
if(fabs(fh)>w2){ // acute bend
fh=k*w2;
aa=1;
}
// next coord pair
fhc=fcc*fh;
fhs=fss*fh;
x3=lround(p2+s+fhc);
y3=lround(q2-c+fhs);
x4=lround(p2-s-fhc);
y4=lround(q2+c-fhs);
}
npp++;
px[npp]=x3; // lower side
py[npp]=y3;
npp++; // upper side
px[npp]=x4;
py[npp]=y4;
return npp;
}
int makeTLCxy(void)
{
int q,n=0;
if(npp<3) return -1;
TLCp.x[0]=px[n];
TLCp.y[0]=py[n];
n++;
TLCp.x[1]=px[n];
TLCp.y[1]=py[n];
// odd points
for(q=3;q<=npp;q+=2){
n++;
TLCp.x[n]=px[q];
TLCp.y[n]=py[q];
}
// even ponts
for(q=npp-1;q>=0;q-=2){
n++;
TLCp.x[n]=px[q];
TLCp.y[n]=py[q];
}
return n;
}
//************************
//TLC readers and writers
//************************
//read a cell record
int readC(void)
{
static char buf[TLCLIM];
char *s;
buf[0]=0;
if(!feof(rTLCfile)){
fgets(buf,TLCLIM,rTLCfile);
strcpy(TLCc.name,chop(buf,9));
fgets(buf,TLCLIM,rTLCfile);
chop(buf,36);
if((s=strtok(buf," "))==NULL) return 0;
TLCc.o=atoi(s) & 0x07;
if((s=strtok(NULL," "))==NULL) return 0;
TLCc.x=atol(s);
if((s=strtok(NULL," "))==NULL) return 0;
TLCc.y=atol(s);
return 1;
}
return 0;
}
//read a box record
int readB(void)
{
static char buf[TLCLIM];
char *s;
buf[0]=0;
if(!feof(rTLCfile)){
fgets(buf,TLCLIM,rTLCfile);
chop(buf,TLCLIM);
if((s=strtok(buf," "))==NULL) return 0;
TLCb.lyr=atoi(s);
if((s=strtok(NULL," "))==NULL) return 0;
TLCb.l=atol(s);
if((s=strtok(NULL," "))==NULL) return 0;
TLCb.b=atol(s);
if((s=strtok(NULL," "))==NULL) return 0;
TLCb.r=atol(s);
if((s=strtok(NULL," "))==NULL) return 0;
TLCb.t=atol(s);
return 1;
}
return 0;
}
//read a path record
int readP(void)
{
static char buf[TLCLIM];
char *s;
int nv=0,p=0;
buf[0]=0;
if(!feof(rTLCfile)){
fgets(buf,TLCLIM,rTLCfile);
chop(buf,TLCLIM);
if((s=strtok(buf," "))==NULL) return 0;
TLCp.lyr=atoi(s);
if((s=strtok(NULL," "))==NULL) return 0;
TLCp.w=atol(s);
if((s=strtok(NULL," "))==NULL) return 0;
nv=TLCp.nv=atoi(s);
fgets(buf,TLCLIM,rTLCfile);
chop(buf,TLCLIM);
if((s=strtok(buf," "))==NULL) return 0;
TLCp.x[p]=atol(s); //1st X
if((s=strtok(NULL," "))==NULL) return 0;
TLCp.y[p]=atol(s); //1st Y
p++;
nv--;
while(nv>0){
if((s=strtok(NULL," "))==NULL){ //end of line read new line
fgets(buf,TLCLIM,rTLCfile);
chop(buf,TLCLIM);
if((s=strtok(buf," "))==NULL) return 0;
}
TLCp.x[p]=atol(s); //keep X
if((s=strtok(NULL," "))==NULL) return 0;
TLCp.y[p]=atol(s); //keep Y
p++;
nv--;
}
return 1;
}
return 0;
}
//read a text record
int readT(void)
{
static char buf[TLCLIM];
char *s;
buf[0]=0;
if(!feof(rTLCfile)){
fgets(buf,TLCLIM,rTLCfile);
chop(buf,TLCLIM);
if((s=strtok(buf," "))==NULL) return 0;
TLCt.lyr=atoi(s);
if((s=strtok(NULL," "))==NULL) return 0;
TLCt.siz=atol(s);
if((s=strtok(NULL," "))==NULL) return 0;
TLCt.nv=atoi(s);
if((s=strtok(NULL," "))==NULL) return 0;
TLCt.o=atoi(s);
//coords
fgets(buf,TLCLIM,rTLCfile);
chop(buf,TLCLIM);
if((s=strtok(buf," "))==NULL) return 0;
TLCt.x=atol(s);
if((s=strtok(NULL," "))==NULL) return 0;
TLCt.y=atol(s);
//text string
fgets(buf,TLCLIM,rTLCfile);
chop(buf,TLCLIM);
strcpy(TLCt.txt,buf);
return 1;
}
return 0;
}
//write TLC header info
void writeH(void)
{
static char buf[10];
fprintf(wTLCfile,"=H\n");
fprintf(wTLCfile,"%s\n",TLCh.name);
fprintf(wTLCfile,"%s\n",TLCh.lv);
fprintf(wTLCfile,"%s\n",TLCh.tv);
fprintf(wTLCfile,"%g\n",TLCh.scale);
fprintf(wTLCfile,"%s\n",TLCh.punit);
fprintf(wTLCfile,"%s\n",_strdate(buf));
fprintf(wTLCfile,"%s\n",_strtime(buf));
fprintf(wTLCfile,"%d %ld %ld %ld %ld\n",TLCh.rnk,TLCh.l,TLCh.b,TLCh.r,TLCh.t);
fprintf(wTLCfile,"%d %d %u %d\n",TLCh.bn,TLCh.pn,TLCh.vn,TLCh.cn);
}
//write a cell record
void writeC(void)
{
TLCh.cn++;
fprintf(wTLCfile,"=C\n");
fprintf(wTLCfile,"%s\n",TLCc.name);
fprintf(wTLCfile,"%d %ld %ld %d\n",TLCc.o,TLCc.x,TLCc.y,0);
}
//write a box record
void writeB(void)
{
TLCh.bn++;
fprintf(wTLCfile,"=B\n");
fprintf(wTLCfile,"%d %ld %ld %ld %ld\n",TLCb.lyr,TLCb.l,TLCb.b,TLCb.r,TLCb.t);
}
//write a path record
void writeP(void)
{
unsigned n=0; //coords start at 0
TLCh.pn++;
TLCh.vn+=TLCp.nv;
fprintf(wTLCfile,"=P\n");
fprintf(wTLCfile,"%d %ld %d\n",TLCp.lyr,TLCp.w,TLCp.nv);
//write 5 vertex/line
while(n<TLCp.nv){
fprintf(wTLCfile,"%ld %ld ",TLCp.x[n],TLCp.y[n]);
n++;
if(!(n % 5)) fprintf(wTLCfile,"\n");
}
if((n % 5)) fprintf(wTLCfile,"\n");
}
//write a text record
void writeT(void)
{
TLCh.pn++;
TLCh.vn+=TLCt.nv;
fprintf(wTLCfile,"=T\n");
fprintf(wTLCfile,"%d %ld %u %d\n",TLCt.lyr,TLCt.siz,TLCt.nv,TLCt.o);
fprintf(wTLCfile,"%ld %ld\n",TLCt.x,TLCt.y);
fprintf(wTLCfile,"%s\n",TLCt.txt);
}
//*****************
//tilter functions
//*****************
//tilt global vars nx,ny,nz
void Tilt(void)
{
if(axis1=='z') tiltZ(cos1,sin1);
if(axis1=='x') tiltX(cos1,sin1);
if(axis1=='y') tiltY(cos1,sin1);
if(axis2=='z') tiltZ(cos2,sin2);
if(axis2=='x') tiltX(cos2,sin2);
if(axis2=='y') tiltY(cos2,sin2);
if(axis3=='z') tiltZ(cos3,sin3);
if(axis3=='x') tiltX(cos3,sin3);
if(axis3=='y') tiltY(cos3,sin3);
}
//tilt on Z axis
void tiltZ(double c,double s)
{
long xtmp,ytmp;
xtmp=(long)(c*nx-s*ny);
ytmp=(long)(s*nx+c*ny);
nz=nz;
nx=xtmp;
ny=ytmp;
}
//tilt on X axis
void tiltX(double c,double s)
{
long xtmp,ytmp;
xtmp=nx;
ytmp=(long)(c*ny-s*nz);
nz=(long)(s*ny+c*nz);
nx=xtmp;
ny=ytmp;
}
//tilt on Y axis
void tiltY(double c,double s)
{
long xtmp,ytmp;
xtmp=(long)(c*nx+s*nz);
ytmp=ny;
nz=(long)(c*nz-s*nx);
nx=xtmp;
ny=ytmp;
}
//****************
//misc. functions
//****************
//open any TLC for read
int ropenTLC(char *name)
{
static char buf[13];
sprintf(buf,"%s.TLC",name);
if((rTLCfile=fopen(buf,"rt"))==NULL)
return 0;
return 1;
}
//open any tilted TLC for write
int wopenTLC(char *name)
{
static char buf[13];
sprintf(buf,"%s.TLC",tiltname(name));
if((wTLCfile=fopen(buf,"wt"))==NULL)
return 0;
return 1;
}
//round double to long
long lround(double f)
{
if(f>=0)
return (long)(f+.5);
else
return (long)(f-.5);
}
char *chop(char *s,int c)
{
int l;
l=strlen(s);
if(s[l-1]=='\n')
s[l-1]='\0'; //remove '\n'
s[c]='\0'; //keep c chars
return s; //return pointer
}
char *tiltname(char *name)
{
static char buf[10];
strcpy(buf,"!");
if(strlen(name)>7)
strncpy(buf+1,name+1,7);
else
strncpy(buf+1,name,7);
buf[8]=0;
return buf;
}
int dsign(double n)
{
if(n>0) return 1;
if(n==0) return 0;
if(n<0) return -1;
}
//check for key abort
int abrtCk(void)
{
int key=0;
if(kbhit()){
key=getch();
if(key==0x1B) return 1;
if(key==0 || key==0xE0) getch();
return 0;
}
return 0;
}
void HELP(void)
{
printf("This utility makes drawings that are useful for presentations. It works on\n");
printf("TLC files in the current directory and rotates objects around any 3 axes\n");
printf("(x,y,z) into a 3-D view. The X-axis is to the right, the Y-axis is upward\n");
printf("and the Z-axis is out of the drawing plane. Rotations are all right-handed.\n");
printf("This program works only on the named cells and not any lesser cells that a\n");
printf("cell might contain. It only works correctly on lesser cells if they are not\n");
printf("not rotated or flipped. Use the FLATTLC.EXE program to make a flat TLC file\n");
printf("if the drawing has nested lesser cells\n");
printf("\n");
printf("The layers and cells are stacked by a constant spacing outward from the\n");
printf("drawing plane. Layer spacing and cell spacing may be different.\n");
printf("\n");
printf(" Command Line: axis=\"x\"or\"y\"or\"z\" []=Optional\n");
printf("\n");
printf(" \"tilt angleaxis angleaxis angleaxis lspace cspace cellname [...cellname]\"\n");
printf("\n");
printf("Angles are in deg, lspace is the layer to layer spacing in physical units\n");
printf("and cspace is the spacing of cells in physical units from the first layer.\n");
printf("\n");
printf(" Example: \"tilt 45z -60x 0y 10 0 cellx\" makes a nice oblique view.\n");
printf("\n");
printf("Press a key to Continue ...");
getch();
_clearscreen(_GCLEARSCREEN);
printf("\nContinued ...\n\n");
printf("On completion, new TLC files will be made that have the ! character added\n");
printf("to the beginning of their name. An original name should not exceed 7 \n");
printf("characters or the first character will be chopped.\n");
printf("\n");
printf("Any cell records found in a TLC file will have their cellnames changed as\n");
printf("above also, so that the tilted lesser cells will be correctly added.\n");
printf("\n");
printf("Composite 3-D views of cells containing other cells may be made by first\n");
printf("tilting the lesser cells, and then the main cell. TLC will then construct\n");
printf("the composite drawing if only the main cell is named.\n");
printf("\n");
printf("Layers and cells may be respaced for best clarity. Using fills and dashed\n");
printf("lines helps greatly to distinguish layers.\n");
printf("\n");
printf("The order of the rotations is important. Mathematically, the rotation\n");
printf("operations do not commute.\n");
printf("\n\n");
printf("Hint: To visualize the rotations, take a rectangular unsymmetric object\n");
printf(" like a floppy disk and rotate it manually in front of you.\n");
printf("\n");
printf("Press a key to Exit ...");
getch();
_clearscreen(_GCLEARSCREEN);
}